package com.base.app_core.ioc.dao;

import android.os.Build;

import com.base.app_core.App;
import com.base.app_core.model.ServerCookies;
import com.base.app_core.model.ServerIP;
import com.base.app_core.service.Retrofit.RestServer;
import com.base.app_core.service.user.model.User;
import com.base.app_core.util.AppConstants;
import com.base.app_core.util.XYBAUtils;
import com.base.app_core.util.MD5Util;
import com.base.app_core.util.Preferences;
import com.base.app_core.util.liteorm.MyIChatDBHelpUtils;
import com.base.app_core.util.log.F;
import com.base.app_core.util.retrofit.MyRequestBodyConverter;
import com.franmontiel.persistentcookiejar.ClearableCookieJar;
import com.franmontiel.persistentcookiejar.PersistentCookieJar;
import com.franmontiel.persistentcookiejar.cache.SetCookieCache;
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;

import com.blankj.utilcode.util.StringUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import javax.inject.Singleton;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import dagger.Module;
import dagger.Provides;
import me.jessyan.retrofiturlmanager.RetrofitUrlManager;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

/**
 * Created by jiansheng.li on 2017/4/26.
 */
@Module
public class HttpApiModule {

    String jwtToken = null;

    @Provides
    @Singleton
    public ServerCookies provideServerCookies(MyIChatDBHelpUtils myIChatDBHelpUtils) {
        ServerCookies serverCookies = (ServerCookies) myIChatDBHelpUtils.getFirstOBj(ServerCookies.class, null, null);
        if (null == serverCookies)
            serverCookies = new ServerCookies();
        return serverCookies;
    }

    @Provides
    @Singleton
    public OkHttpClient provideOkHttpClient(final User user, final ServerCookies serverCookies, final MyIChatDBHelpUtils myIChatDBHelpUtils) {
        final OkHttpClient.Builder builder = new OkHttpClient.Builder();
//        final HashMap<String, List<Cookie>> cookieStore = new HashMap<String, List<Cookie>>();
//        final PersistentCookieStore persistentCookieStore = new PersistentCookieStore(App.getContext());
        builder.connectTimeout(60 * 1000, TimeUnit.MILLISECONDS)
                .readTimeout(60 * 1000, TimeUnit.MILLISECONDS);
//        try {
//            final TrustManager[] trustAllCerts = new TrustManager[]{
//                    new X509TrustManager() {
//                        @Override
//                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
//                        }
//
//                        @Override
//                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
//                        }
//
//                        @Override
//                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
//                            return new java.security.cert.X509Certificate[]{};
//                        }
//                    }
//            };
//            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
//            trustManagerFactory.init(getKeyStore());
//            SSLContext sslContext = SSLContext.getInstance("TLS");
//            sslContext.init(null, /*trustManagerFactory.getTrustManagers()*/trustAllCerts, null);
//            builder.sslSocketFactory(sslContext.getSocketFactory());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                F.j("==============hostname >" + hostname);
                return true;
            }
        });

        builder.addInterceptor(new Interceptor() {
            private Request injectParamsIntoUrl(HttpUrl.Builder httpUrlBuilder, Request.Builder requestBuilder, Map<String, String> paramsMap) {
                if (paramsMap.size() > 0) {
                    Iterator iterator = paramsMap.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry entry = (Map.Entry) iterator.next();
                        httpUrlBuilder.addQueryParameter((String) entry.getKey(), (String) entry.getValue());
                    }
                }
                requestBuilder.url(httpUrlBuilder.build());
                return requestBuilder.build();
            }

            Map<String, String> queryParamsMap = new HashMap<>();

            @Override
            public Response intercept(Chain chain) throws IOException {
                //获取到request
                Request request = chain.request();
                if (null == user || !user.getLogin())
                    return chain.proceed(request);
                Request.Builder builder = request.newBuilder();//获取到方法
//                if(null!=user&&user.isLogin()){
//                    queryParamsMap.put(AppConstants.FIE\LD.USERID, user.getUser_id()+"");
//                }
                request = injectParamsIntoUrl(request.url().newBuilder(), builder, queryParamsMap);

                Response response = chain.proceed(request);
//                request=builder.build();
                //最后通过chain.proceed(request)进行返回
                String token = response.header("Authorization");
                if (!StringUtils.isEmpty(token)) {
                    jwtToken = token;
                    Preferences.putString(AppConstants.SP.JWTOKEN, jwtToken);
                    F.j("jwtToken=" + jwtToken);
                }
                return response;
            }
        });

        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Request.Builder builder = request.newBuilder();
                if (StringUtils.isEmpty(jwtToken)) {
                    jwtToken = Preferences.getDefault().getString(AppConstants.SP.JWTOKEN, null);
                }
                if (!StringUtils.isEmpty(jwtToken)) {
                    builder.addHeader("Authorization", "Bearer " + jwtToken);
                }
                builder.addHeader("Accept-Encoding", "identity");//http://blog.csdn.net/zoudifei/article/details/49963437
                builder.addHeader("Random", String.valueOf(Math.random()));//http://blog.csdn.net/zoudifei/article/details/49963437
                builder.addHeader("version", XYBAUtils.getVersion(App.getContext()));//http://blog.csdn.net/zoudifei/article/details/49963437
                builder.addHeader("identifi", Preferences.getDefault().getString(AppConstants.SP.IMEI, ""));
                builder.addHeader("Platform", "Android");//http://blog.csdn.net/zoudifei/article/details/49963437
                builder.addHeader("method", String.valueOf(1));
                builder.addHeader("md5", MD5Util.encrypt(bodyToString(request) + "djdl#@%&Eedass"));
                request = builder.build();
                return chain.proceed(request);
            }
        });

        ClearableCookieJar cookieJar =
                new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(App.getContext()));
        builder.cookieJar(cookieJar);
        // 网路拦截器
        builder.networkInterceptors().add(new Interceptor() {
            public Response intercept(Chain chain) throws IOException {
                Response response = null;
                ResponseBody responseBody = null;
                try {
                    Request.Builder builder = chain.request().newBuilder();
                    if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13)
                        builder.addHeader("Connection", "close");
                    Request request = chain.request();
                    String requestLog = String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers().toString());
                    if (request.method().compareToIgnoreCase("post") == 0)
                        requestLog = "\n" + requestLog + "\n" + bodyToString(request);
                    F.http("request" + "\n" + requestLog);
                    response = chain.proceed(builder.build());
                    //这里不能直接使用response.body().string()的方式输出日志
                    //因为response.body().string()之后，response中的流会被关闭，程序会报错，我们需要创建出一
                    //个新的response给应用层处理
                    responseBody = response.peekBody(1024 * 1024 * 100);
                    F.http("respond \n" + response.request().url() + " -" + responseBody.string() + "-" + response.headers());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    responseBody.close();
                }

                return response;
            }
        });
        return RetrofitUrlManager.getInstance().with(builder)
                .build();
    }

//    private KeyStore getKeyStore() {
//        InputStream inputStream = null;
//        if(BuildConfig.BUILD_TYPE.equals("dev"))
//            inputStream = App.getContext().getResources().openRawResource(R.raw.kachemama_dev);
//        else if(BuildConfig.BUILD_TYPE.equals("local"))
//            inputStream = App.getContext().getResources().openRawResource(R.raw.kachemama_dev);
//        else if(BuildConfig.BUILD_TYPE.equals("pro"))
//            inputStream = App.getContext().getResources().openRawResource(R.raw.kachemama_dev);
//        else if(BuildConfig.BUILD_TYPE.equals("sta"))
//            inputStream = App.getContext().getResources().openRawResource(R.raw.kachemama_dev);
//        else
//            inputStream = App.getContext().getResources().openRawResource(R.raw.kachemama_dev);
//        try {
//            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
//            Certificate certificate = certificateFactory.generateCertificate(inputStream);
//            KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
//            keyStore.load(null, null);
//            keyStore.setCertificateEntry("trust", certificate);
//            return keyStore;
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        } finally {
//            try {
//                inputStream.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//    }


    private String bodyToString(final Request request) {
        try {
            final Request copy = request.newBuilder().build();
            final Buffer buffer = new Buffer();
            copy.body().writeTo(buffer);
            return buffer.readUtf8();
        } catch (final IOException e) {
            return "did not work";
        }
    }

    @Provides
    @Singleton
    public RestServer provideGithubApiService(OkHttpClient okHttpClient, MyIChatDBHelpUtils myIChatDBHelpUtils) {
        if (myIChatDBHelpUtils != null) {
            List<ServerIP> serverIPS = myIChatDBHelpUtils.getQueryAll(ServerIP.class);
            if (serverIPS != null && serverIPS.size() != 0) {
                AppConstants.SERVER_URL = serverIPS.get(new Random().nextInt(serverIPS.size())).getUrl();
                F.j("switchse:" + AppConstants.SERVER_URL);
            }
        }

        Retrofit retrofit = new Retrofit.Builder().client(okHttpClient)
                .addConverterFactory(MyRequestBodyConverter.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(AppConstants.SERVER_URL)
                .build();

//        Retrofit.Builder builder = new Retrofit.Builder();
//        builder.client(okHttpClient).baseUrl("http://m-dev.kachemama.com/mobile/").addConverterFactory(GsonConverterFactory.create());
        return retrofit.create(RestServer.class);
    }


}
